package com.panopset.java;

import java.io.File;
import java.io.StringWriter;
import java.util.Vector;

/**
 * Format source pre-compile time.
 *
 * @author Karl Dinwiddie
 *
 */
public final class FormatSource {

    /**
     * FormatSource constructor.
     *
     * @param srcDir
     *            Java source directory that is to be formatted.
     */
    private FormatSource(final File srcDir) {
        format(srcDir);
    }

    /**
     * args[0] = Java source code directory.
     * @param args
     *            args[0] is the source root directory that you wish to format.
     */
    public static void main(final String[] args) {
        if (args == null) {
            return;
        }
        if (args.length != 1) {
            return;
        }
        File dir = new File(args[0]);
        if (!dir.exists()) {
            return;
        }
        if (!dir.isDirectory()) {
            return;
        }
        new FormatSource(dir);
    }

    /**
     * Format a Java source file.  Files without ".java" extension are ignored.
     * @param src Source file.
     */
    private void format(final File src) {
        if (src.isFile()) {
            if (com.panopset.Util.getExtension(src).equals(".java")) {
                com.panopset.Util.saveStringToFile(
                        format(com.panopset.Util.loadFile(src)), src);
            }
        } else if (src.isDirectory()) {
            for (File f : src.listFiles()) {
                format(f);
            }
        }
    }

    /**
     * Search string, split on two lines to ensure that it is not replaced
     * when FormatSource changes the real one.
     */
    private static final String APP_VERSION_ASSIGNMENT = "private static "
            + "final String UNI_VERSION =";

    /**
     * Pre-compile time replacement line.
     */
    private static final String REPLACEMENT_LINE = "    "
            + APP_VERSION_ASSIGNMENT + " \""
            + UniversalVersion.asUniversalVersion().createNewVersion() + "\";";

    /**
     * Format a vector of Java source lines.
     * @param Java source file stored in a Vector &lt; String &gt;.
     * @return Formatted Java source.
     */
    private static String format(final Vector < String > src) {
        StringWriter sw = new StringWriter();
        int i = 0;
        int lastPopulated = -1;
        for (String s : src) {
            if (!s.trim().equals("")) {
                lastPopulated = i;
            }
            i++;
        }
        i = 0;
        FOR: for (String s : src) {
            if (i <= lastPopulated) {
                if (s.indexOf(APP_VERSION_ASSIGNMENT) > -1) {
                    s = REPLACEMENT_LINE;
                }
                sw.append(trimEnd(s).replace("\u0009", "    "));
                sw.append(com.panopset.Util.getReturnChar());
            } else {
                break FOR;
            }
            i++;
        }
        return sw.toString();
    }

    /**
     * For unit testing, format an array of Strings.
     * @param src String[] array of source lines.
     * @return Formatted java source.
     */
    public static String format(final String[] src) {
        Vector < String > v = new Vector < String > ();
        for (String s : src) {
            v.add(s);
        }
        return format(v);
    }

    /**
     *
     * Trim the spaces off the end of a String.
     * From: <a href="http://java-interview-faqs.blogspot.com/2009/07/playing-with-java-
     * string-trim-basics.html">java-interview-faqs.blogspot.com/2009/07/playing-with-java-
     * string-trim-basics.html</a>.
     *
     * @param s String.
     * @return String s without any trailing spaces.
     */
    public static String trimEnd(String s) {
        if (s != null) {
            while (s.endsWith(" ")) {
                s = s.substring(0, s.length() - 1);
            }
        }
        return s;
    }
}
